#include "Bot.h"
#include "Logger.h"
using namespace std;

//constructor
Bot::Bot()
{

};

//plays a single game of Ants.
void Bot::playGame()
{
    //reads the game parameters and sets up
    Logger::theLogger() << "Reading initial state" << endl;
    cin >> state;
    state.setup();
    endTurn();
    Logger::theLogger() << "Turn 0 completed" << endl;

    //continues making moves while the game is not over
    while(cin >> state)
    {
	Logger::theLogger() << "Starting updateVision" << endl;
        state.updateVisionInformation();
	Logger::theLogger() << "Finished updateVision" << endl;

	Logger::theLogger() << "Starting analyzeMap" << endl;
	state.analyzeMap();
	Logger::theLogger() << "Finished analyzeMap" << endl;

	Logger::theLogger() << "Starting makeMoves" << endl;
        makeMoves();
	Logger::theLogger() << "Finished makeMoves" << endl;
        endTurn();
    }
};


//Make a random move, 
//TODO: Not very random, need to shuffle directions before looping.
void Bot::randomMove(int ant) {
    for(int d=0; d<TDIRECTIONS; d++)
    {
	Location loc = state.getLocation(state.ants[ant], d);
	
	if(!state.grid[loc.row][loc.col].isWater && (state.grid[loc.row][loc.col].ant==-1))
	{
	    Logger::theLogger() << "Random Move: " << loc.row << "," << loc.col << endl;
	    state.makeMove(state.ants[ant], d);
	    break;
	}
    }
}

//Try to find a closest food and move towards it.
//by other ants.
bool Bot::huntFood(int ant) {
    Location antLoc = state.ants[ant];
    Location foodLoc;
    stack<int> path;
    int numNodesExplored=0;
    if (state.findClosestFood(antLoc,foodLoc,path,numNodesExplored)) {
	if (!path.empty()) {
	    Logger::theLogger() << "Ant at: " << antLoc.row << "," <<antLoc.col << endl;
	    Logger::theLogger() << "Found food: " << foodLoc.row << "," << foodLoc.col << endl;
	    Logger::theLogger() << "numNodesExplored:" << numNodesExplored << endl;
	    //Now check if the food is already being tracked and if
	    //we try and acquire only if one of the following conditions holds true
	    // a) current max path length to the food is > path length for this ant 
	    // TODO b) enemy ant has a shorter path than current max path length
	    if (state.grid[foodLoc.row][foodLoc.col].tracking>0) {
		int maxPathLength = state.foodTrackingPathLengths[foodLoc];
		if (maxPathLength > path.size()) {
		    Location nLoc = state.getLocation(state.ants[ant],path.top());
		    if (nLoc!=foodLoc && state.grid[nLoc.row][nLoc.col].ant!=0) {
			state.grid[foodLoc.row][foodLoc.col].tracking+=1;
			state.foodTrackingPathLengths[foodLoc] = path.size();
			state.makeMove(state.ants[ant],path.top());
			path.pop();
			return true;
		    }
		}
		else {
		    return false;
		}
	    }
	    else {
		Location nLoc = state.getLocation(state.ants[ant],path.top());
		if (nLoc!=foodLoc && state.grid[nLoc.row][nLoc.col].ant!=0) {
		    state.grid[foodLoc.row][foodLoc.col].tracking+=1;
		    state.foodTrackingPathLengths[foodLoc] = path.size();
		    state.makeMove(state.ants[ant],path.top());
		    path.pop();
		    return true;
		}
	    }
	    return false;
	}
	else {
	    Logger::theLogger() << "Oops found food but path is empty" << endl;
	}
    }
    return false;
}

//Try to find a closest food and move towards it.
//by other ants.
bool Bot::huntAnts(int ant) {
    Location antLoc = state.ants[ant];
    Location enemyAntLoc;
    stack<int> path;
    int numNodesExplored=0;
    if (state.findClosestEnemyAnt(antLoc,enemyAntLoc,path,numNodesExplored)) {
	Logger::theLogger() << "Ant at: " << antLoc.row << "," <<antLoc.col << endl;
	Logger::theLogger() << "Found enemyAnt: " << enemyAntLoc.row << "," << enemyAntLoc.col << endl;
	Logger::theLogger() << "numNodesExplored:" << numNodesExplored << endl;
	if (!path.empty()) {
	    Location nLoc = state.getLocation(state.ants[ant],path.top());
	    if (nLoc!=enemyAntLoc && state.grid[nLoc.row][nLoc.col].ant!=0) {
		state.grid[enemyAntLoc.row][enemyAntLoc.col].tracking+=1;
		state.makeMove(state.ants[ant],path.top());
		path.pop();
	    }
	    return true;
	}
	else {
	    Logger::theLogger() << "Oops found an enemyAnt but path is empty" << endl;
	}
    }
    return false;
}

//makes the bots moves for the turn
void Bot::makeMoves()
{
    Logger::theLogger() << "turn " << state.turn << ":" << endl;
    Logger::theLogger() << state << endl;

    //picks out moves for each ant
    for(int ant=0; ant<(int)state.ants.size(); ant++)
    {
	if (!huntFood(ant)) {
	    if (!huntAnts(ant)) {
		randomMove(ant);
	    }
	}
    }

    Logger::theLogger() << "Move time taken: " << state.timer.getTime() << "ms" << endl << endl;
};

//finishes the turn
void Bot::endTurn()
{
    if(state.turn > 0)
        state.reset();
    state.turn++;

    cout << "go" << endl;
};
